package prototype;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

// -------------------------- 1. 辅助类：订单相关子对象（需支持序列化实现深克隆） --------------------------
// 商品类（实现Serializable支持序列化深克隆）
class Product implements Serializable {
    private String productId;
    private String name;
    private double price;
    private int stock;  // 可变引用类型成员

    public Product(String productId, String name, double price, int stock) {
        this.productId = productId;
        this.name = name;
        this.price = price;
        this.stock = stock;
    }

    // Getter和Setter
    public String getProductId() { return productId; }
    public void setStock(int stock) { this.stock = stock; }
    public int getStock() { return stock; }

    @Override
    public String toString() {
        return String.format("Product(productId=%s, name=%s, price=%.2f, stock=%d)",
                productId, name, price, stock);
    }
}

// 收货地址类（实现Serializable）
class Address implements Serializable {
    private String userId;
    private String province;
    private String city;
    private String detail;

    public Address(String userId, String province, String city, String detail) {
        this.userId = userId;
        this.province = province;
        this.city = city;
        this.detail = detail;
    }

    // Setter
    public void setUserId(String userId) { this.userId = userId; }

    @Override
    public String toString() {
        return String.format("Address(province=%s, city=%s, detail=%s)",
                province, city, detail);
    }
}

// -------------------------- 2. 抽象原型：订单原型接口 --------------------------
interface OrderPrototype extends Serializable {
    OrderPrototype clone();  // 克隆接口（支持序列化深克隆）
    void initComplexData(String userId, List<String> productIds);  // 复杂初始化
}

// -------------------------- 3. 具体原型：电商订单（实现深克隆） --------------------------
class EcommerceOrder implements OrderPrototype {
    private String orderId;
    private String userId;
    private double totalAmount;
    private String status;
    private Address address;  // 引用类型成员
    private List<Product> products;  // 引用类型成员（列表）

    // 原型初始化（仅执行一次复杂逻辑）
    public EcommerceOrder(String userId, List<String> productIds) {
        this.orderId = generateOrderId();
        this.initComplexData(userId, productIds);
        this.userId = userId;
        this.status = "pending";
    }

    // 生成唯一订单号
    private String generateOrderId() {
        return "ORDER-" + UUID.randomUUID().toString().substring(0, 12).toUpperCase();
    }

    // 模拟复杂初始化：查询地址、商品（仅原型创建时执行）
    @Override
    public void initComplexData(String userId, List<String> productIds) {
        // 1. 模拟查询用户地址
        this.address = new Address(userId, "广东省", "深圳市", "南山区科技园路1号");
        // 2. 模拟查询商品信息
        this.products = new ArrayList<>();
        // 模拟数据库商品数据
        Product p1001 = new Product("p1001", "iPhone 15", 6999.0, 100);
        Product p1002 = new Product("p1002", "AirPods Pro", 1799.0, 200);
        Product p1003 = new Product("p1003", "MacBook Pro", 13999.0, 50);

        for (String pid : productIds) {
            switch (pid) {
                case "p1001":
                    products.add(p1001);
                    break;
                case "p1002":
                    products.add(p1002);
                    break;
                case "p1003":
                    products.add(p1003);
                    break;
            }
        }
        // 3. 计算默认总金额
        this.totalAmount = products.stream().mapToDouble(Product::getStock).sum();
    }

    // 深克隆实现：通过序列化（推荐，避免手动递归复制）
    @Override
    public EcommerceOrder clone() {
        try {
            // 1. 序列化：将对象写入字节流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            // 2. 反序列化：从字节流读取新对象（深克隆）
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            EcommerceOrder newOrder = (EcommerceOrder) ois.readObject();

            // 3. 修改克隆后的差异属性（生成新订单号）
            newOrder.orderId = generateOrderId();
            return newOrder;
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("订单克隆失败：" + e.getMessage());
        }
    }

    // 自定义克隆方法：支持修改差异属性
    public EcommerceOrder cloneWithParams(String userId, double totalAmount, String status, boolean reduceStock) {
        EcommerceOrder newOrder = this.clone();
        // 修改差异属性
        if (userId != null) {
            newOrder.userId = userId;
            newOrder.address.setUserId(userId);  // 更新地址的用户ID
        }
        if (totalAmount > 0) {
            newOrder.totalAmount = totalAmount;
        }
        if (status != null) {
            newOrder.status = status;
        }
        // 克隆时减库存（验证深克隆）
        if (reduceStock) {
            newOrder.products.forEach(p -> p.setStock(p.getStock() - 1));
        }
        return newOrder;
    }

    // Getter：用于验证深克隆
    public List<Product> getProducts() { return products; }

    @Override
    public String toString() {
        StringBuilder productsStr = new StringBuilder();
        for (Product p : products) {
            productsStr.append("\n  ").append(p);
        }
        return String.format(
                "EcommerceOrder(\n" +
                        "  orderId=%s,\n" +
                        "  userId=%s,\n" +
                        "  totalAmount=%.2f,\n" +
                        "  status=%s,\n" +
                        "  address=%s,\n" +
                        "  products=[%s\n  ]\n" +
                        ")",
                orderId, userId, totalAmount, status, address, productsStr
        );
    }

    // -------------------------- 4. 客户端使用 --------------------------
    public static void main(String[] args) {
        // 1. 创建原型订单
        System.out.println("=== 创建原型订单 ===");
        List<String> productIds = new ArrayList<>();
        productIds.add("p1001");
        productIds.add("p1002");
        EcommerceOrder prototypeOrder = new EcommerceOrder("user_001", productIds);
        System.out.println(prototypeOrder);

        // 2. 批量克隆订单
        System.out.println("\n=== 批量克隆订单 ===");
        EcommerceOrder order1 = prototypeOrder.cloneWithParams(
                "user_002", 8798.0, "pending", true  // 减库存
        );
        System.out.println("订单1（用户002，减库存）:");
        System.out.println(order1);

        EcommerceOrder order2 = prototypeOrder.cloneWithParams(
                "user_003", 8598.0, "paid", false  // 已支付，不减库存
        );
        System.out.println("\n订单2（用户003，已支付）:");
        System.out.println(order2);

        // 3. 验证深克隆
        System.out.println("\n=== 验证深克隆 ===");
        int prototypeStock = prototypeOrder.getProducts().get(0).getStock();
        int order1Stock = order1.getProducts().get(0).getStock();
        System.out.printf("原型订单商品1库存: %d%n", prototypeStock);  // 100
        System.out.printf("订单1商品1库存: %d%n", order1Stock);        // 99
    }
}